{% extends "tutorial.html" %}

{% block headauthor %}Ernest Delgado <ernestd@chromium.org>{% endblock %}

{% block headtitle %}HTML5 Video{% endblock %}
{% block pagetitle %}HTML5 Video{% endblock %}
{% block pagebreadcrumb %}HTML5 Video{% endblock %}
{% block head %}
<style>
video, canvas {
  width: 200px;
  height: 112px;
  border: 1px solid black;
}

.video-container {
  display: inline-block;
  text-align: center;
}

.video_stream { color: blue; }
.audio_stream { color: red; }
.file_format { color: green; }

/* video-js */
#control-icons {
  position: absolute;
  background-color: white;
  margin-left: 177px;
  border: 1px solid #ccc;
}

#volume-mix {
  position: absolute;
  margin-left: 140px;
  margin-top: 130px;
}

/* video-css */
#video-css {
  -moz-transition: all 0.3s ease-out;  /* FF3.7+ */
  -o-transition: all 0.3s ease-out;  /* Opera 10.5 */
  -webkit-transition: all 0.3s ease-out;  /* Saf3.2+, Chrome */ 
}

@-webkit-keyframes crawl {
  0% { -webkit-transform: translate(0, 10px);  }
  25% { -webkit-transform: translate(2px, 5px); }
  50% { -webkit-transform: translate(0, 0); }
  75% { -webkit-transform: translate(-2px, 5px); }
  1000% { -webkit-transform: translate(0, 10px);  }
}

#video-css.enhanced {
  border: 1px solid white;
  
  -moz-box-shadow: 0px 0px 4px #ffffff; /* FF3.5+ */
  -webkit-box-shadow: 5px 44px 28px #333; /* Saf3.0+, Chrome */
  box-shadow: 0px 0px 4px #ffffff; /* Opera 10.5, IE 9.0 */

  -moz-transform: translate(0, -10px);  /* FF3.5+ */
  -o-transform: translate(0, -10px);  /* Opera 10.5 */
  -webkit-transform: translate(0, -10px);  /* Saf3.1+, Chrome */
  
  -webkit-animation-name: crawl;
  -webkit-animation-duration: 2s;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: ease-in-out;
}

/* video-svg */
.offscreen { position: absolute; left: -2000px; }

#canvas-draw-frames, #canvas-svg-draw { 
  display: none;
}
</style>
{% endblock %}
{% block date %}August 3rd, 2010{% endblock %}

{% block browsersupport %}
<span class="browser opera supported"><span class="browser_name">Opera</span><span class="support">supported</span></span> <span class="browser ie"><span class="browser_name">Internet Explorer</span><span class="support">unsupported</span></span> <span class="browser safari supported"><span class="browser_name">Safari</span><span class="support">supported</span></span> <span class="browser ff supported"><span class="browser_name">Firefox</span><span class="support">supported</span></span> <span class="browser chrome supported"><span class="browser_name">Chrome</span><span class="support">supported</span></span>
{% endblock %}

{% block html5badge %}
<img src="/static/images/identity/html5-badge-h-multimedia.png" width="133" height="64" alt="This article is powered by HTML5 Multimedia" title="This article is powered by HTML5 Multimedia"  />
{% endblock %}

{% block iscompatible %}
  return Modernizr.video;
{% endblock %}

{% block content %}
  <h2 id="toc-intro">Introducción</h2>
  <p>
    La etiqueta de vídeo es una de las funciones de HTML5 que suscitan más interés. Esta etiqueta se suele presentar como alternativa a Flash para el contenido multimedia, pero tiene más aplicaciones. Aunque recientemente se ha incorporado al resto de etiquetas HTML omnipresentes, sus posibilidades y su compatibilidad con diferentes navegadores han aumentado a una increíble velocidad. Como se puede ver en este tutorial, la ventaja principal de la etiqueta de vídeo es la posibilidad de integración natural con las demás capas de la pila de desarrollo web, como CSS y JavaScript, así como con las otras etiquetas HTML.
  </p>
  <p>
    En este tutorial se explican los aspectos básicos de la etiqueta de vídeo y se muestran ejemplos de diferentes integraciones con otras funciones de HTML5, como el elemento &lt;canvas&gt;.
  </p>
  <h2 id="toc-markup">1. El marcado</h2>
  <p>
    Las líneas de código que se muestran a continuación deben ser suficientes para que funcione el vídeo HTML en un sitio web.
  </p>
<pre class="prettyprint">
&lt;video>
  &lt;source src="movie.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  &lt;source src="movie.webm" type='video/webm; codecs="vp8, vorbis"' />
&lt;/video></pre>
  <p>
    En este fragmento se utiliza la etiqueta <em>&lt;source&gt;</em>, que permite incluir varios formatos como tipos alternativos en caso de que el navegador del usuario no admita alguno de ellos. En la siguiente sección se ofrece más información sobre este tema.
  </p>
  <p>
    También se puede utilizar un único formato de vídeo que haga que la sintaxis sea muy parecida a la de la etiqueta de imagen. Esta sintaxis será la más utilizada en un futuro próximo cuando todos los navegadores admitan un formato de vídeo común.
  </p>
<pre class="prettyprint">&lt;video src="movie.webm">&lt;/video></pre>
  <p>
    Por el momento, nos centraremos en el primer caso, que actualmente es el más común. <em>Lo más importante que debes recordar</em> es que tienes que asegurarte de que tu servidor muestre los archivos de vídeo con el tipo MIME correcto en el encabezado <code>Content-Type</code>. De lo contrario, los vídeos podrían no funcionar correctamente (aunque sí funcionen en una copia local del sitio). En un archivo de configuración "httpd.conf" de Apache, solo habría que añadir estas líneas:
  </p>
<pre class="prettyprint">
AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm
</pre>
  <p>
    Si tu aplicación se muestra a través de Google App Engine, tendrás que añadir un bloque parecido al siguiente en el archivo "app.yaml" (uno por cada formato):
  </p>
<pre class="prettyprint">
- url: /(.*\.ogv)
  static_files: videos_folder/\1
  mime_type: video/ogg
  upload: videos_folder/(.*\.ogv)
</pre>
  <p>
    Para mejorar el rendimiento del cliente, es importante no olvidarse de especificar el atributo <em>type</em> en las etiquetas <em>source</em> cuando se tenga que hacer referencia a varios formatos. De ese modo, el navegador podrá decidir qué formatos puede descargar y reproducir y no descargará los formatos que no pueda reproducir para aumentar el rendimiento del sitio.
  </p>
  
  <h2 id="toc-formats">2. Formatos de vídeo</h2>
  <p>
    El concepto de <span class="file_format">formato de vídeo</span> se puede entender como un archivo zip que contiene <span class="video_stream">secuencias de vídeo</span> y <span class="audio_stream">secuencias de audio</span>. Los tres formatos que se deben tener en cuenta para la Web son WebM, MP4 y OGV:
  </p>
  <ul>
    <li><span class="file_format">.mp4</span> = <span class="video_stream">H.264</span> + <span class="audio_stream">AAC</span></li>
    <li><span class="file_format">.ogg/.ogv</span> = <span class="video_stream">Theora</span> + <span class="audio_stream">Vorbis</span></li>
    <li><span class="file_format">.webm</span> = <span class="video_stream">VP8</span> + <span class="audio_stream">Vorbis</span></li>
  </ul>
  <p>
    La velocidad de evolución de la etiqueta de vídeo es verdaderamente alentadora. Hace tan solo un año, el único navegador que admitía la etiqueta de vídeo en su versión estable era Safari. Ahora, todos los navegadores actuales admiten vídeo HTML5, incluido IE9, la última versión del navegador Internet Explorer. En cuanto a los códecs, Firefox, Chrome y Opera han acordado admitir WebM como formato de vídeo común a través del <a href="http://webmproject.org">proyecto WebM</a>. Internet Explorer también admitirá ese formato <em>si</em> el códec se instala en el ordenador (esperemos que este requisito no sea imprescindible en el futuro).
  </p>
  <p>
    <em>Nota:</em> en el momento de escribir este artículo, Safari no admite el formato WebM.
  </p>
  <p>
    A continuación se muestra un ejemplo en el que se observa que el navegador solo puede mostrar uno o dos de los tres formatos mencionados (¡puedes sentirte afortunado si tu navegador admite los tres formatos!):
  </p>
  {% if is_mobile %}
  <div class="video-container">
    <p>.mp4</p>
    <video poster="star.png" controls>
      <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    </video>
  </div>
  <div class="video-container">
    <p>.webm</p>
    <video poster="star.png" controls>
      <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
    </video>
  </div>
  <div class="video-container">
    <p>.ogv</p>
    <video poster="star.png" controls>
      <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
    </video>
  </div>
  {% else %}
  <iframe src="http://playground.html5rocks.com/?mode=frame&hu=180&hl=180#video_formats" style="border: none; width: 100%; height: 480px;"></iframe>
  {% endif %}

  <p>
    En el momento de escribir este artículo (agosto de 2010), este es el fragmento que ofrece la combinación de formatos más segura para que el vídeo se muestre en todos los navegadores:
  </p>
<pre class="prettyprint">
&lt;video>
  &lt;source src="movie.webm" type='video/webm; codecs="vp8, vorbis"' />
  &lt;source src="movie.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  &lt;source src="movie.ogv" type='video/ogg; codecs="theora, vorbis"' />
  Video tag not supported. Download the video &lt;a href="movie.webm">here&lt;/a>.
&lt;video></pre>
  <p>
    <em>Nota:</em> debido a un error del iPad, hay que indicar .mp4 como primera opción si se quiere que el vídeo se cargue en ese dispositivo. Hasta que se corrija el error, claro...
  </p>

  <p>
    Como se ha indicado anteriormente, casi todos los proveedores de navegadores aceptaron admitir un formato de vídeo común. Por tanto, en menos de un año, el código que probablemente se utilizará en toda la Web será el siguiente:
  </p>
<pre class="prettyprint">
&lt;video>
  &lt;source src="movie.webm" type='video/webm; codecs="vp8, vorbis"' />
  &lt;source src="movie.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  Video tag not supported. Download the video &lt;a href="movie.webm">here&lt;/a>.
&lt;video></pre>
  
  <p>
    Uno de los principales problemas relacionados con el uso del formato .mp4 es que su códec de vídeo (h.264) no es un códec abierto y que las licencias que tendría que pagar una empresa para utilizarlo son bastante complejas. En <a href="http://diveintohtml5.info/video.html#licensing">este capítulo sobre vídeos</a>, se ofrece más información acerca de este formato.
  </p>
  <p>
    Otro problema que afecta al formato .mp4 es que el atributo <em>type</em> tiene que ser más específico que otros formatos dependiendo del perfil que se utilice para codificar el vídeo. Aunque el más común es "avc1.42E01E, mp4a.40.2", es importante comprobar <a href="http://wiki.whatwg.org/wiki/Video_type_parameters#MPEG-4">esta lista de perfiles</a> para asegurarse.
  </p>
  <p>
    Aunque Microsoft anunció que la versión 9 de su navegador Internet Explorer (IE9) admitiría la etiqueta de vídeo, así como otros elementos HTML5, su tasa de migración de usuarios a versiones más recientes es inferior a la de los demás navegadores principales. Esto nos lleva a la siguiente sección:
  </p>
  
  <h2 id="toc-fallback">3. ¿Qué pasa con las versiones actuales de IE que no admiten la etiqueta de vídeo?</h2>
  <h3 id="toc-fallback-flash">Flash como alternativa</h3>
  <p>Flash también puede ser una solución alternativa. Según cuál sea el formato del vídeo, es posible que haya que volver a codificarlo con un formato compatible para el reproductor Flash. La buena noticia es que Adobe se ha comprometido a admitir el formato <em>WebM</em> en su reproductor Flash, aunque no se sabe con certeza cuándo se podrá empezar a utilizar. Sin embargo, el mayor inconveniente que tiene esta solución en comparación con la del complemento Chrome Frame es que se obtiene el reproductor Flash como versión degradada de la interfaz de usuario personalizada o de las funciones mejoradas que se hayan utilizado para la etiqueta de vídeo. En el tutorial <a href="http://tutorials.html5rocks.com/tutorials/audio/quick/#toc-step3">Guía rápida de implementación de la etiqueta de audio de HTML5</a>, se ofrece información detallada sobre esta técnica.</p>
  
  <h2 id="toc-encode">4. Codificación de los vídeos</h2>
  <p>
    Si necesitas codificar tus vídeos en los formatos mencionados en la sección anterior, puedes utilizar <a href="http://www.mirovideoconverter.com/">el conversor Miro Video Converter</a> para Windows y Mac para conseguir fácilmente el formato que necesites. El programa no permite hacer muchos cambios de configuración, pero ofrece los formatos más comunes de la Web, incluidos los tres formatos utilizados en este tutorial. En realidad, este software es un contenedor de <a href="http://ffmpeg.org/">ffmpeg</a> y <a href="http://v2v.cc/~j/ffmpeg2theora/">ffmpeg2theora</a> que se puede utilizar en Windows, Mac y Linux desde la línea de comandos (especificando más parámetros en caso necesario). En <a href="http://diveintohtml5.info/video.html#webm-cli">divintohtml5.org</a>, se ofrece más información sobre esta herramienta.
  </p>

  <h2 id="toc-fun">5. La parte divertida</h2>
  <p>
    Como se indicó en la introducción, la principal ventaja de la pertenencia de la etiqueta de vídeo a la familia HTML5 es la posibilidad de integración con las demás capas de la pila de desarrollo web. En los siguientes ejemplos se ofrece una visión general de lo que se puede hacer con ella.
  </p>
  <h3 id="toc-fun-html">5.1. Vídeo + otros elementos HTML</h3>
  <p>
    Todos los atributos HTML comunes se pueden utilizar ahora en el reproductor de vídeo. Por ejemplo, en el fragmento que aparece a continuación, se utiliza <em>tabindex</em> para poder acceder a los controles del reproductor. Hay algunos atributos nuevos que se pueden utilizar en la etiqueta de vídeo que también son comunes a la etiqueta de audio, como el atributo de reproducción continua (<em>loop</em>) y el de reproducción automática (<em>autoplay</em>). El atributo <em>poster</em> indica qué imagen se mostrará durante la carga inicial del vídeo y al final de su reproducción, mientras que <em>controls</em> se utiliza para indicar que, en lugar de crear controles personalizados, queremos que el navegador muestre los controles automáticamente. También hay un atributo <em>preload</em>, que se puede utilizar para descargar el vídeo en segundo plano en cuanto se carga la página aunque no haya empezado a reproducirse.
  </p>
<pre class="prettyprint">
&lt;video <em>poster="star.png" autoplay loop controls tabindex="0"</em>&gt;
  &lt;source src="movie.webm" type='video/webm; codecs="vp8, vorbis"' /&gt;
  &lt;source src="movie.ogv" type='video/ogg; codecs="theora, vorbis"' /&gt;
&lt;/video&gt;
</pre>
  <p>
    El nivel completo de integración de la etiqueta de vídeo como elemento nativo del navegador acaba con algunos problemas que se podían presentar antes con los reproductores externos insertados, como la superposición de iframes y menús desplegables en el reproductor o una apariencia extraña cuando se ajustaba de forma dinámica el tamaño de los <em>otros elementos HTML</em> que rodeaban el vídeo.
  </p>
  <p>
    Al no tratarse el vídeo como un elemento ajeno insertado, el usuario tiene otras ventajas. Por ejemplo, aunque el foco de atención se encuentre en el reproductor, se pueden realizar perfectamente acciones como desplazarse por la página o pulsar teclas del teclado.
  </p>

  <p>
    <em>Nota:</em> si intentas crear <a href="http://dev.w3.org/html5/html-author/#polyglot-documents">documentos políglotas</a> para mantener la sintaxis de XHTML en el contexto de HTML5, los atributos de tu código deben estar definidos del siguiente modo:
  </p>
<pre class="prettyprint">
&lt;video <em>poster="star.png" autoplay="autoplay" loop="loop" controls="controls" tabindex="0"</em>&gt;
  &lt;source src="movie.webm" type='video/webm; codecs="vp8, vorbis"' /&gt;
  &lt;source src="movie.ogv" type='video/ogg; codecs="theora, vorbis"' /&gt;
&lt;/video&gt;
</pre>

  <h3 id="toc-fun-js">5.2. Vídeo + JavaScript</h3>
  <p>
    La etiqueta de vídeo incluye una serie de atributos y de métodos que permiten tener un buen control del vídeo mediante el código JavaScript utilizado. Puedes verlos en tiempo real en <a href="http://www.w3.org/2010/05/video/mediaevents.html">este ejemplo</a>.
  </p>
  <p>
    Al igual que ocurre con los demás elementos HTML, se pueden añadir eventos comunes a la etiqueta de vídeo (por ejemplo, eventos del ratón, eventos de arrastre, enfoque, etc.), pero el elemento de vídeo incluye una serie de nuevos eventos que permiten detectar (y controlar) el momento de reproducción, pausa o finalización del vídeo. Como la carga de un recurso de vídeo puede tener muchas condiciones, hay múltiples eventos que permiten llevar a cabo el debido control del proceso de carga, tanto en la red (loadstart, progress, suspend, abort, error, emptied, stalled) como en el búfer (<code>loadedmetadata</code>, loadeddata, waiting, playing, canplay, canplaythrough).
  </p>
  <p>
    En su nivel más básico, se puede añadir el evento "canplay" para empezar a hacer cosas con el vídeo.
  </p>
<pre class="prettyprint">
video.addEventListener('canplay', function(e) {
  this.volume = 0.4;
  this.currentTime = 10;
  this.play();
}, false);
</pre>
  <p>
    Actualmente, hay varios controles de reproductores personalizados disponibles en Internet. En el ejemplo que aparece a continuación, se utilizan algunos elementos para controlar dos vídeos de forma simultánea y se emula el efecto de avance rápido con el atributo <em>playbackRate</em>. Utiliza el control deslizante para cambiar el volumen entre los vídeos.
  </p>
  <div id="control-icons">
    <img src="control-skip-180.png" id="rw" />
    <img src="control.png" id="play" />
    <img src="control-double.png" id="ff" />
  </div>
  <input type="range" min="0" max="100" value="25" id="volume-mix" />

  <video poster="star.png" id="video-left" tabindex="0">
    <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>

  <video poster="star.png" id="video-right" tabindex="0">
    <source src="chromeicon.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    <source src="chromeicon.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="chromeicon.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>

  <h3 id="toc-fun-css">5.3. Vídeo + CSS</h3>
  <p>
    Como podrás imaginarte, se puede aplicar estilo a la etiqueta de vídeo con propiedades CSS tradicionales (p. ej., bordes, opacidad, etc.), ya que esta etiqueta es uno de los elementos principales del DOM, pero lo mejor es que también se le pueden aplicar las últimas propiedades CSS3, como reflejos, máscaras, gradientes, transformaciones, transiciones y animaciones.
  </p>
  <p>
    Coloca el cursor sobre el siguiente vídeo para ver cómo funcionan algunas de estas propiedades.
  </p>
  <video poster="star.png" id="video-css">
    <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>
  
<pre class="prettyprint">
#video-css.enhanced {
  border: 1px solid white;
  -moz-box-shadow: 0px 0px 4px #ffffff; /* FF3.5+ */
  -webkit-box-shadow: 5px 44px 28px #333; /* Saf3.0+, Chrome */
  box-shadow: 0px 0px 4px #ffffff; /* Opera 10.5, IE 9.0 */

  -moz-transform: translate(0, 10px);  /* FF3.5+ */
  -o-transform: translate(0, 10px);  /* Opera 10.5 */
  -webkit-transform: translate(0, 10px);  /* Saf3.1+, Chrome */
}
</pre>

  <h3 id="toc-fun-canvas">5.4. Vídeo + canvas</h3>
  <p>
    El elemento canvas es otro elemento HTML5 que ofrece muchas posibilidades cuando se utiliza junto con la etiqueta de vídeo.
  </p>
  <p>
    En el ejemplo que aparece a continuación, se utilizan dos funciones del elemento &lt;canvas&gt; para importar y exportar imágenes. La primera es el método <em>drawImage</em>, que permite importar imágenes de tres fuentes diferentes: un elemento de imagen, otro elemento canvas y un elemento <em>&lt;video&gt;</em>. Esto significa que, cada vez que se ejecute este método, el marco actual del vídeo se importará y se mostrará en el elemento canvas.
  </p>
  <p>
    La segunda función de la etiqueta &lt;canvas&gt; que se utiliza es el método <em>toDataURL</em>, que permite exportar el contenido del elemento canvas a una imagen. Haz clic en el botón de reproducción del vídeo que aparece a continuación para ver cómo se crea una imagen a partir del vídeo cada 1,5 segundos. En realidad, el elemento canvas utilizado para la importación/exportación está <em>oculto</em>.
  </p>
  <video poster="star.png" id="video-canvas-frames" controls>
    <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>
  <canvas id="canvas-draw-frames"></canvas>
  <div id="frames"></div>
  <p>
    En el código que aparece a continuación, se puede ver que simplemente se ha creado un intervalo que se ejecuta cada 1,5 segundos con el método drawImage que utiliza el elemento de vídeo como fuente.
  </p>
<pre class="prettyprint">
video_dom.addEventListener('play', function() {
  video_dom.width = canvas_draw.width = video_dom.offsetWidth;
  video_dom.height = canvas_draw.height = video_dom.offsetHeight;
  var ctx_draw = canvas_draw.getContext('2d');
  draw_interval = setInterval(function() {
    // import the image from the video
    ctx_draw.drawImage(video_dom, 0, 0, video_dom.width, video_dom.height);
    // export the image from the canvas
    var img = new Image();
    img.src = canvas_draw.toDataURL('image/png');
    img.width = 40;
    frames.appendChild(img);
  }, 1500)
}, false);
</pre>
  <p>
    En el siguiente ejemplo, daremos un paso más. Si se aumenta la frecuencia con la que se debe importar y mostrar la imagen del vídeo, se puede emular la misma frecuencia de vídeo en el elemento canvas. De esta forma, se pueden hacer todo tipo de transformaciones en el elemento canvas como si se estuvieran realizando en el propio vídeo.
  </p>
  <p>
    En la parte izquierda, se puede ver la reproducción de vídeo original. En el centro, aparece un elemento canvas que se utiliza para importar las imágenes cada 33 milisegundos. En la parte derecha, aparece otro elemento canvas que "sufrirá" todas las transformaciones al mismo tiempo que importa las imágenes del primer elemento canvas. El único motivo por el que se utilizan dos elementos canvas es porque así se consigue un rendimiento muy superior al que se puede conseguir utilizando un único elemento canvas que importe las imágenes y se transforme al mismo tiempo.
  </p>
  {% if is_mobile %}
  <video poster="star.png" id="video-canvas-fancy" controls>
    <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
    <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>
  <canvas id="canvas-copy-fancy"></canvas>
  <canvas id="canvas-draw-fancy"></canvas>
  {% else %}
  <iframe src="http://playground.html5rocks.com/?mode=frame&hu=180&hl=160#video_+_canvas" style="border: none; width: 100%; height: 460px;"></iframe>
  {% endif %}

  <p>
    Esta misma técnica de importación de imágenes se puede aplicar también a <a href="https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/WebGL-spec.html">WebGL</a>. Si utilizas WebGL, deberías poder importar los marcos de un vídeo y mostrarlos en un cubo giratorio en 3D, por ejemplo. En el <a href="https://developer.mozilla.org/en/WebGL/Animating_textures_in_WebGL">sitio web de MDN</a>, se ofrece más información sobre esta implementación.
  </p>
  <h3 id="toc-fun-svg">5.5. Vídeo + SVG</h3>
  <p>
    SVG permite mostrar y manipular gráficos vectoriales mediante programación, pero también incluye más funciones, como los <a href="http://en.wikipedia.org/wiki/SVG_filter_effects">efectos de filtro SVG</a>. Estos filtros permiten elegir un elemento DOM específico y aplicarle algunos efectos especiales como los de mosaicos, difuminado, composición, etc. En el momento de escribir este artículo (agosto de 2010), Firefox 4 e IE9 admiten la integración de SVG, que permite utilizar HTML y CSS en el elemento de vídeo (en este ejemplo, se utilizan JavaScript y el elemento canvas para garantizar también el funcionamiento en navegadores que aún no admitan la integración de SVG):
  </p>
<pre class="prettyprint">
&lt;svg id='image' version="1.1" xmlns="http://www.w3.org/2000/svg"> 
  &lt;defs>
    &lt;filter id="myblur"> 
      &lt;feGaussianBlur stdDeviation="1" /> 
    &lt;/filter>
  &lt;/defs>
&lt;/svg>
&lt;style>
  video { filter:url(#myblur); border: 2px solid red; }
&lt;/style>
</pre>
  <div class="video-container">
    <p>Haz clic en la imagen para cambiar el filtro de difuminado</p>
    <video poster="star.png" id="video-svg">
      <source src="Chrome_ImF.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
      <source src="Chrome_ImF.webm" type='video/webm; codecs="vp8, vorbis"' />
      <source src="Chrome_ImF.ogv" type='video/ogg; codecs="theora, vorbis"' />
    </video>
  </div>
  <div id="svg"></div>
  <canvas id="canvas-svg-draw"></canvas>

  <script>
    // video-js
    (function() {
      var v1 = document.querySelector('#video-left')
      var v2 = document.querySelector('#video-right')
      var rw = document.querySelector('#rw')
      var play = document.querySelector('#play')
      var ff = document.querySelector('#ff')
      var volume = document.querySelector('#volume-mix')
      var volume_value = 0;
      rw.addEventListener('click', function() {
        v1.pause();
        v2.pause();
        v1.currentTime = 0;
        v2.currentTime = 0;
      }, false);
      ff.addEventListener('click', function() {
        v1.play();
        v2.play();
        v1.playbackRate = 3;
        v2.playbackRate = 3;
      }, false);
      play.addEventListener('click', function() {
        if (v1.paused && v2.paused) {
          v1.play();
          v2.play();        
        } else {
          v1.pause();
          v2.pause();
        }
      }, false);
      v1.addEventListener('play', function() {
        setVolume();
      }, false);
      volume.addEventListener('change', function() {
        setVolume();
      }, false);
      function setVolume() {
        volume_value = volume.value - 50;
        if (volume_value < 0) {
          v2.volume = 0;
          v1.volume = (volume_value * (-1) * 2) / 100;
        } else {
          v1.volume = 0;
          v2.volume = (volume_value * 2) / 100;
        }
      }
    })();
    
    // video-css
    (function() {
      var video_css = document.querySelector('#video-css');
      video_css.addEventListener('mouseover', function() {
        this.className = 'enhanced';
        try { // some bug in chrome is throwing an exception here
          this.currentTime = '8';          
        } catch(err) {}
        this.play();
        tryRoundedCorners();
      }, false);
      video_css.addEventListener('mouseout', function() {
        this.pause();
        try { // some bug in chrome is throwing an exception here
          this.currentTime = 0;
        } catch(err) {}
        this.className = '';
      }, false);

      function tryRoundedCorners() {
        setTimeout(function() {
          video_css.style.borderRadius = '60px';
        }, 3000);
        setTimeout(function() {
          video_css.style.borderRadius = '0';
        }, 6000);      
      }
    })();
    
    // video + canvas (sample 1)
    (function() {
      var video_dom = document.querySelector('#video-canvas-frames');
      var canvas_draw = document.querySelector('#canvas-draw-frames');
      var frames = document.querySelector('#frames');
      var draw_interval = null;
      
      video_dom.addEventListener('play', function() {
        video_dom.width = canvas_draw.width = video_dom.offsetWidth;
        video_dom.height = canvas_draw.height = video_dom.offsetHeight;
        var ctx_draw = canvas_draw.getContext('2d');
        draw_interval = setInterval(function() {
          ctx_draw.drawImage(video_dom, 0, 0, video_dom.width, video_dom.height);
          var img = new Image();
          img.src = canvas_draw.toDataURL('image/png');
          img.width = 40;
          frames.appendChild(img);
        }, 1500)
      }, false);
      video_dom.addEventListener('pause', function() {
        clearInterval(draw_interval);
      }, false);
      video_dom.addEventListener('ended', function() {
        clearInterval(draw_interval);
      }, false);
    })();

  {% if is_mobile %}
    // video + canvas (sample 2)
    (function() {
      var video_dom = document.querySelector('#video-canvas-fancy');
      var canvas_copy = document.querySelector('#canvas-copy-fancy');
      var canvas_draw = document.querySelector('#canvas-draw-fancy');
      var draw_interval = null;
      var ctx_copy = null;
      var ctx_draw = null;
      
      var offsets = [];
      var inertias = [];
      var slices = 4;
      var out_padding = 100;
      var interval = null;

      var inertia = -2.0;
      
      video_dom.addEventListener('canplay', function() {
        canvas_copy.width = canvas_draw.width = video_dom.videoWidth;
        canvas_copy.height = video_dom.videoHeight;
        canvas_draw.height = video_dom.videoHeight + out_padding;
        ctx_copy = canvas_copy.getContext('2d');
        ctx_draw = canvas_draw.getContext('2d');
      }, false);
      
      
      for (var i = 0; i < slices; i++) {
        offsets[i] = 0;
        inertias[i] = inertia;
        inertia += 0.4;
      }
      
      video_dom.addEventListener('play', function() {
        processEffectFrame();
        if (interval == null) {
          interval = window.setInterval(function() { processEffectFrame() }, 33);
        }        
      }, false);
      
      function processEffectFrame() {
        var slice_width = video_dom.videoWidth / slices;
        ctx_copy.drawImage(video_dom, 0 ,0);
        ctx_draw.clearRect(0, 0,  canvas_draw.width, canvas_draw.height);
        for (var i = 0; i < slices; i++) {
          var sx = i * slice_width;
          var sy = 0;
          var sw = slice_width;
          var sh = video_dom.videoHeight;
          var dx = sx;
          var dy = offsets[i] + sy + out_padding;
          var dw = sw;
          var dh = sh;
          ctx_draw.drawImage(canvas_copy, sx, sy, sw, sh, dx, dy, dw, dh);
          if (Math.abs(offsets[i] + inertias[i]) < out_padding) {
            offsets[i] += inertias[i];
          } else {
            inertias[i] = -inertias[i];
          }
        }
      };
      
      video_dom.addEventListener('pause', function() {
        window.clearInterval(interval);
        interval = null;
      }, false);
      video_dom.addEventListener('ended', function() {
        clearInterval(interval);
      }, false);  
    })();
  {% endif %}

    // video + svg
    // insert SVG using script until SVG in HTML5 is more widely supported
    // (currently supported in IE 9 and Firefox 4 only)
    (function() {
      window.addEventListener('DOMContentLoaded', function() {
        var container = document.getElementById('svg');
        var svgns = 'http://www.w3.org/2000/svg';
        var xlinkns = 'http://www.w3.org/1999/xlink';
        var svg = document.createElementNS(svgns, 'svg');
        svg.setAttribute('width', 200);
        svg.setAttribute('height', 112);
        svg.setAttribute('class', 'offscreen');

        // our linearGradient
        var defs = document.createElementNS(svgns, 'defs');
        var filter = document.createElementNS(svgns, 'filter');
        filter.setAttribute('id', 'myblur');
        var feGaussianBlur = document.createElementNS(svgns, 'feGaussianBlur');
        feGaussianBlur.setAttribute('stdDeviation', '2');
        filter.appendChild(feGaussianBlur);
        defs.appendChild(filter);
        svg.appendChild(defs);

        var imageEl = document.createElementNS(svgns, 'image');
        imageEl.setAttributeNS(xlinkns, "href", "star.png");
        imageEl.setAttribute('id', 'image-data-el');
        imageEl.setAttribute('width', 200);
        imageEl.setAttribute('height', 112);
        var g = document.createElementNS(svgns, "g");
        g.appendChild(imageEl);
        svg.appendChild(g);

        container.appendChild(svg);

        var video_dom = document.querySelector('#video-svg');
        var canvas_draw = document.querySelector('#canvas-svg-draw');
        var draw_interval = null;
        var ctx_draw = null;
        var image_data = null;
        var image_data_el = document.querySelector('#image-data-el');

        video_dom.addEventListener('canplay', function() {
          video_dom.width = canvas_draw.width = video_dom.offsetWidth;
          video_dom.height = canvas_draw.height = video_dom.offsetHeight;
          ctx_draw = canvas_draw.getContext('2d');
        }, false);

        video_dom.addEventListener('click', function() {
          this.play();
          this.style.display = 'none';
          svg.setAttribute('class', '');
          image_data_el.style.filter = 'url(#myblur)';
        }, false);

        svg.addEventListener('click', function() {
          video_dom.pause();
          video_dom.style.display = 'block';
          svg.setAttribute('class', 'offscreen');
        }, false);

        video_dom.addEventListener('play', function() {
          draw_interval = setInterval(function() {
            ctx_draw.drawImage(video_dom, 0, 0, video_dom.width, video_dom.height);
            image_data = canvas_draw.toDataURL('image/png');
            image_data_el.setAttributeNS(xlinkns, "href", image_data);
          }, 33);
        }, false);
        video_dom.addEventListener('pause', function() {
          clearInterval(draw_interval);
        }, false);
        video_dom.addEventListener('ended', function() {
          clearInterval(draw_interval);
        }, false);
      }, false);
    })();
  </script>
  
{% endblock %}